using System;
using System.Collections.Generic;
using System.Text;

namespace Blimpbots.Recognition
{
    public class GenerativeExample : RecognitionExample
    {
        public RecognitionExample _parent;

        public int DetectionCount = 0;
        public int CopyCount = 0;

        public bool[] KeypointValidity;

        Point2D originalOffset;

        bool _valid = false;

        public bool Valid { get { return _valid; } }

        // Generative examples are "validated"
        //  when they are detected as undergoing a significant shift
        //  in the image scene.

        // TODO: better idea: generative examples are "validated" when their
        //       inliers contain several keypoints that match the original model

        public RecognitionExample Parent { get { return _parent; } }

        public GenerativeExample(RecognitionExample parent, List<CorrespondingKeypoint>[] corresp, AffineTransform t)
        {
            _corresp = corresp;

            if (parent.GetType() == typeof(GenerativeExample))
            {
                _parent = ((GenerativeExample)parent).Parent;
                CopyCount = ((GenerativeExample)parent).CopyCount + 1;
            }
            else
            {
                _parent = parent;
                CopyCount = 1;
            }
            originalOffset = t.Offset;
        }

        public void ObserveTransform(AffineModel am)
        {
            int validCount = 0;
            foreach(KeypointMatch km in am.Inliers)
                if(KeypointValidity[km.modelIdx])
                    validCount++;

            if (validCount > 4) // at least 5 kpts -- this seems the minimum allowable!
            {
                _valid = true;

                double shift_Magnitude = am.Transform.Offset.Distance(originalOffset);
                // object has moved 15 pixels
                if (shift_Magnitude > 15.0)
                {
                    // we've shifted AND more than 3 keypoints are known valid
                    // so assume this model is good and validate the rest
                    foreach (KeypointMatch km in am.Inliers)
                        KeypointValidity[km.modelIdx] = true;
                }
            }
        }
    }
}
